# 文件指针
filePtr = None;
# 当前字符
ch = ' '
# 打开文件
def openFile(filename = 'test.pl0'):
    global filePtr
    filePtr = open(filename,'r')
# 关键字常量
CON_SYM = 0; # const
VAR_SYM = 1; # var
PRO_SYM = 2; # procedure
BEG_SYM = 3; # begin
END_SYM = 4; # end 
OOD_SYM = 5; # ood
IF_SYM = 6;  # if
THE_SYM = 7; # then
WHI_SYM = 8; # while
DO_SYM = 9;     # do
REA_SYM = 10;   # read
CAL_SYM = 11;   # call
WRI_SYM = 12;   # write
# 符号常量
GIV_SYM = 20;   # :=
EQ_SYM = 21;    # =
LB_SYM = 22;    # (
RB_SYM = 23;    # )
SEM_SYM = 24;   # ;
COM_SYM = 25;   # ,
DOT_SYM = 26;   # .
# 自定义终结符常量
ID_SYM = 30;    # 标识符
UN_SYM = 31;    # 数字
RE_SYM = 32;    # > < >= <= ==
MN_SYM = 33;    # + -
TD_SYM = 34;    # * /
OVE_SYM = 35;   # #

':=','=','(',')',';',',','.','id','un','re','mn','td'
# 所有关键字
keywordSet = {'const','var','procedure','begin','end','ood','if','then','while','do','read','call','write'}
# 关键字-类型映射
keywordSymMap = {'const':CON_SYM,'var':VAR_SYM,'procedure':PRO_SYM,'begin':BEG_SYM,'end':END_SYM,'ood':OOD_SYM,'if':IF_SYM,
'then':THE_SYM,'while':WHI_SYM,'do':DO_SYM,'read':REA_SYM,'call':CAL_SYM,'write':WRI_SYM}
# 符号-类型映射
symSymMap = {'+':MN_SYM,'-':MN_SYM,'*':TD_SYM,'/':TD_SYM,'(':LB_SYM,')':RB_SYM,';':SEM_SYM,',':COM_SYM,'.':DOT_SYM}
# 单词类
class Token:
    # typ 类型有三种，关键字 标识符，数字
    # iden 存储符号
    # val 存储值
    def __init__(self,typ,iden,val):
        self.typ = typ;
        self.iden = iden;
        self.val = val;

# 从打开的文件中读取一个字符
def getch():
    global ch
    if filePtr == None:
        return None;
    ch = filePtr.read(1);
    # print(ch,end='')
    # print('%s %d' % (ch,ord(ch)))
    # 读到文件末尾
    if len(ch) == 0:
        # 设置为结束符号
        ch = '#'
# 判断字符是否为字母
def isAlpha(ch):
    return (ch <= 'z' and ch >= 'a') or (ch <= 'Z') and (ch >= 'A');
# 判断字符是否为数字
def isDigit(ch):
    return (ch <= '9' and ch >= '0')
# 读取一个单词，返回一个三元组(类型，名称，值)
def getToken():

    while(ch == ' ' or ch == '\t' or ch == '\n'):
        getch()
    # print('ch is %s'%ch)
    # 可能为标识符或者关键字
    if isAlpha(ch):
        # 用于读出整个单词
        curToken = ''
        while isAlpha(ch) or isDigit(ch):
            # 拼接
            curToken += ch
            # 继续读
            getch()
        # 如果是关键字
        if curToken in keywordSet:
            return (keywordSymMap[curToken],None,None);
        # 如果是标识符
        else:
            return (ID_SYM,curToken,None);
    # 如果遇到的是数字，只能是数字
    elif isDigit(ch):
        num = 0;
        while isDigit(ch):
            num = num * 10 + ord(ch) - ord('0')
            getch()
        return (UN_SYM,None,num)
    elif ch == ':':
        getch();
        if ch == '=':
            getch()
            return (GIV_SYM,None,'=')
    elif ch == '>':
        getch()
        if ch == '=':
            getch()
            return (RE_SYM,None,'>=')
        else:
            return (RE_SYM,None,'>')
    elif ch == '=':
        getch()
        if ch == '=':
            return (RE_SYM,None,'==')
        else:
            return (EQ_SYM,None,None)
    elif ch == '<':
        getch()
        if ch == '=':
            getch()
            return (RE_SYM,None,'<=')
        else:
            return (RE_SYM,None,'<')


    # 其他的单个符号
    else:
        # 读到文末
        if ch == '#':

            return (OVE_SYM,None,'#')
        temp = ch;
        getch()
        return (symSymMap[temp],None,None)
        #while 
# 关闭文件
def closeFile(filename = 'test.pl0'):
    global filePtr
    filePtr.close()
if __name__ == '__main__':
    openFile();
    token = (0,0,0)
    while(token[2] != '#'):
        token = getToken()
        print(token)
    closeFile()
    # print(isAlpha('a'))